#include "project_config.h"

#if (SHELL_ENABLE == 1)

#if (HAVE_FREERTOS == 1)
#include "FreeRTOS.h"
#include "task.h"
#include "queue.h"
#endif
#include "qelib.h"
#include "driver/qe_device.h"



QELOG_DOMAIN("shell");



static qe_shell shell;
static qe_dev *uartdev;

#if (HAVE_FREERTOS == 1)
static int rx_indicate_size = 0;
static QueueHandle_t rx_msgq;
#endif

#if (SHELL_ENDLINE_MODE == 1)
static void shell_log_output(const char *message)
{
    qe_shell_write_end_line(&shell, (char *)message, qe_strlen(message));
}
#endif

#if (HAVE_FREERTOS == 1)
static qe_ret rx_indicate(struct qe_device *dev, qe_size size)
{
    char event;
    BaseType_t woken = pdFALSE;
    qe_assert(rx_msgq);
    rx_indicate_size = size;
    xQueueSendFromISR(rx_msgq, &event, &woken);
    portYIELD_FROM_ISR(woken);
    return qe_ok;
}
#endif

int shell_read(char *data, int len)
{
    int n = 0;

#if (HAVE_FREERTOS == 1)
    char event;
    if (pdPASS == xQueueReceive(rx_msgq, &event, portMAX_DELAY)) {
        return qe_dev_read(uartdev, 0, data, len);
    }
#else
    n = qe_dev_read(uartdev, 0, data, len);
#endif
    
    return n;
}

int shell_write(char *data, int len)
{
    return qe_dev_write(uartdev, 0, data, len);
}

static void shell_task(void *args)
{
	char data;

    qe_memset(&shell, 0x0, sizeof(shell));

#if (HAVE_FREERTOS == 1)
    rx_msgq = xQueueCreate(8, sizeof(char));
    qe_assert(rx_msgq);
#endif

    uartdev = qe_dev_find(SHELL_DEVICE);
    qe_assert(uartdev);

#if (HAVE_FREERTOS == 1)
    qe_dev_set_rx_indicate(uartdev, rx_indicate);
    qe_dev_open(uartdev, QE_DEV_F_INT_RX);
#else
    qe_dev_open(uartdev, 0);
#endif
    
    qe_shell_init(&shell, 4096,
    	SHELL_USER, shell_read, shell_write);

    while (1) {
        if (shell.read && shell.read(&data, 1) == 1) {
            qe_shell_handler(&shell, data);
        }
    }
}

static qe_init int shell_launch(void)
{
	qe_debug("shell launch");

#if (HAVE_FREERTOS == 1)
    xTaskCreate(shell_task, "shell", 0x800, QE_NULL, 3, QE_NULL);
#else
    shell_task(QE_NULL);
#endif

    return 0;
}
QE_APP_EXPORT(shell_launch);

QE_SHELL_EXPORT_USR(SHELL_USER, SHELL_PASSWORD, mb user);
#endif
